
#include <BRender>
#include <BViewer>
#include <BPainter>
#include <BKeyEvent>
#include <BMouseEvent>
#include <BStyle>
#include <BSystem>

#include "PixmapArea.h"
#include "DrawLineStripeFilter.h"

DrawLineStripeFilter::DrawLineStripeFilter(BEventFilter* parent) : BEventFilter(parent)
{
	_hoverIndex = -1;
	connect(this, Signal_AssetChanged, &DrawLineStripeFilter::slotAssetChanged);

}
DrawLineStripeFilter::~DrawLineStripeFilter()
{

}

void DrawLineStripeFilter::slotAssetChanged(BObject* object, const BValue& value)
{
	LineStripe* target = value;
	this->setEnabled(target);
}

void DrawLineStripeFilter::attached(BWidget* widget)
{
	LineStripe* lineStripe = this->asset();
	_lineStripe = lineStripe;
	if (const BStyle* style = widget->realStyle())
	{
		_dragImage = style->image("drag");
	}
}
void DrawLineStripeFilter::detached(BWidget* widget)
{
	_lineStripe = 0;
	_dragImage = 0;
	_hoverPoint = 0;
	_hoverIndex = -1;
}

void DrawLineStripeFilter::updateEvent(const BEvent& event)
{

}

void DrawLineStripeFilter::styleEvent(const BEvent& event)
{
	if (const BStyle* style = event.value())
	{
		_dragImage = style->image("drag");
	}
}
void DrawLineStripeFilter::freshEvent(const BEvent& event)
{

}
void DrawLineStripeFilter::paintEvent(const BEvent& event)
{
	PixmapArea* pixmapArea = (PixmapArea*)this->host();
	BPoint offset = pixmapArea->offset() + _lineStripe->pos();

	BPainter painter(pixmapArea);

	painter.setPointSmooth(true);
	painter.setPointSize(5);
	painter.setColor(200, 200, 0);
	for (int i = 0; i < _lineStripe->pointCount(); i++)
	{
		BPoint point = _lineStripe->point(i);
		painter.drawPoint(point + offset);
	}

	if (_hoverIndex >= 0)
	{
		const BPoint& point = _lineStripe->point(_hoverIndex);
		painter.setColor(200, 0, 200);
		painter.drawPoint(point + offset);
	}
	else if (_selectedIndices.size())
	{
		for (int i = 0; i < _selectedIndices.size(); i++)
		{
			int index = _selectedIndices[i];
			const BPoint& point = _lineStripe->point(index);
			painter.setColor(0, 100, 200);
			painter.drawPoint(point + offset);
		}
	}
	else
	{
		painter.setColor(200, 0, 0);
		painter.drawPoint(_hoverPoint + offset);
	}
}

void DrawLineStripeFilter::keyPressEvent(const BKeyEvent& keyEvent)
{
	if (keyEvent.key() == Key_Escape)
	{
		_selectedIndices.clear();
		this->fresh();
	}
}

void DrawLineStripeFilter::mouseEnterEvent(const BMouseEvent& mouseEvent)
{
	_hoverIndex = -1;
}
void DrawLineStripeFilter::mouseLeaveEvent(const BMouseEvent& mouseEvent)
{
	_hoverIndex = -1;
}
void DrawLineStripeFilter::mousePressEvent(const BMouseEvent& mouseEvent)
{
	if (mouseEvent.keyState(Key_Ctrl))
		return;
	const BPoint& pos = mouseEvent.pos();
	if (mouseEvent.button() == Button_Left)
	{
		_pressedPoint = pos;
		_selectedPoints.clear();
		for (int i = 0; i < _selectedIndices.size(); i++)
		{
			int index = _selectedIndices[i];
			const BPoint& point = _lineStripe->point(index);
			_selectedPoints.append(point);
		}
		this->fresh();
		mouseEvent.accept();
	}
}
void DrawLineStripeFilter::mouseReleaseEvent(const BMouseEvent& mouseEvent)
{
	if (mouseEvent.keyState(Key_Ctrl))
		return;
	if (mouseEvent.button() == Button_Left)
	{
		_selectedPoints.clear();
		this->fresh();
		mouseEvent.accept();
	}
}
void DrawLineStripeFilter::mouseMoveEvent(const BMouseEvent& mouseEvent)
{
	PixmapArea* pixmapArea = (PixmapArea*)this->host();
	BPoint offset = pixmapArea->offset() + _lineStripe->pos();
	Button button = mouseEvent.button();
	if (mouseEvent.button() == Button_None)
	{
		BPoint pos = mouseEvent.pos() - offset;
		int hoverIndex = -1;
		for (int i = 0; i < _lineStripe->pointCount(); i++)
		{
			const BPoint& point = _lineStripe->point(i);
			if ((point - pos).length() < 4)
			{
				hoverIndex = i;
				break;
			}
		}
		if (_hoverIndex != hoverIndex)
		{
			_hoverIndex = hoverIndex;
			this->fresh();
		}
		if (_hoverPoint != pos)
		{
			_hoverPoint = pos;
			this->fresh();
		}
		mouseEvent.accept();
	}
	if (mouseEvent.button() == Button_Left)
	{
		BPoint pos = mouseEvent.pos();
		for (int i = 0; i < _selectedIndices.size(); i++)
		{
			int index = _selectedIndices[i];
			const BPoint& point = _selectedPoints[i];
			BPoint offset = pos - _pressedPoint;
			_lineStripe->setPoint(index, point + offset);
		}
		mouseEvent.accept();
	}
}

void DrawLineStripeFilter::mouseClickEvent(const BMouseEvent& mouseEvent)
{
	if (mouseEvent.keyState(Key_Ctrl))
		return;
	const BPoint& pos = mouseEvent.pos();
	if (mouseEvent.button() == Button_Left)
	{
		if (_hoverIndex >= 0)
		{
			if (BSystem::KeyState(Key_Ctrl))
			{
				if (_selectedIndices.contain(_hoverIndex))
					_selectedIndices.remove(_hoverIndex, 1);
				else
					_selectedIndices.append(_hoverIndex);
			}
			else
			{
				if (!_selectedIndices.contain(_hoverIndex))
				{
					_selectedIndices.clear();
					_selectedIndices.append(_hoverIndex);
				}
			}
			_hoverIndex = -1;
		}
		else
		{
			PixmapArea* pixmapArea = (PixmapArea*)this->host();
			BPoint point = pos - pixmapArea->offset() - _lineStripe->pos();
			_lineStripe->appendPoint(point);
		}
		this->fresh();
		mouseEvent.accept();
	}
}
